﻿#include "pch.h"
#include <iostream>
#include <string>
#include <Windows.h>  //引入Windows库
#include <thread>  //引入线程
#include <sstream>
using namespace std;
//电梯开门时间
#define OPEN_TIME 420
//电梯上升时间
#define UP_TIME 1000

enum  State
{
	Up,
	Down,
	Wait,
};
static int ElevatorSum = 0;
static bool Up_Button = false;
static bool Down_Button = false;
static bool Stop_Timer = false;
class Elevator {
public:
	Elevator();
	~Elevator();
	int Get_MinFloor();  //获取最低楼层值
	int Get_MaxFloor();  //获取最高楼层值
	float Get_MaxHeight();  //获取最大高度
	float Get_MinHeight();  //获取最小高度
	int Get_FloorNum();  //获取楼层总数
	int Get_StopFloor();  //获取当前停止楼层
	void Set_StopFloor(int floor);  //设置电梯当前停止楼层
	void Set_FloorSection(int min, int max);  //设置可到达的楼层区间
	void Set_HeightSection(float min, float max);  //设置可到达的高度区间
	void Set_MaxWeight(float num);  //设置最大载重量
	void Show_ElevatorInfo();  //显示电梯信息
	string Transform_Enum(State curr);  //转换枚举状态
	void Run_Elevator(string dir);  //电梯运行
	void Print_Line(int leng);  //打印横线
	void Open_Door(); //开门操作
	void Input_FloorBtn(Elevator *ele); //楼层按钮操作

public:
	bool Up_State = false;  //上行状态
	bool Down_State = false;  //下行状态
	State Current_State = Wait;  //电梯当前状态
	int Run_Step = 1;  //上升步进值
	int *Floor_Btn = NULL;  //按下的楼层按钮
	string Elevator_Name = "";  //电梯名称
	string Index_Tag = "E";  //遍历标识
private:
	int Floor_Num = 6;  //楼层总数
	int Minimun_Floor = -1;  //可到达的最低楼层
	int Higest_Floor = 5;  //可到达的最高楼层
	int Stop_Floor = -1;  //当前停止楼层
	float Weight_Max = 100.0;  //最大载重量
	float Height_Max = 20.0;   //上升到达最大高度
	float Height_Min = 0.0;   //下降到达最小高度
	string Door_State = "关闭";  //电梯门开闭
};
Elevator:: Elevator() {
	this->Floor_Btn = new int[this->Floor_Num];
}
Elevator:: ~Elevator() {
	delete []this->Floor_Btn;   //释放按钮数组空间
	cout << "扔垃圾" << endl;
}
void Elevator::Set_FloorSection(int min, int max) {
	this->Minimun_Floor = min;
	this->Higest_Floor = max;
	this->Floor_Num = abs((max - min));
}
void Elevator::Set_HeightSection(float min, float max) {
	this->Height_Max = max;
	this->Height_Min = min;
}
void Elevator::Set_MaxWeight(float num) {
	this->Weight_Max = num;
}
int Elevator::Get_MaxFloor() {
	return this->Higest_Floor;
}
int Elevator::Get_MinFloor() {
	return this->Minimun_Floor;
}
float Elevator::Get_MaxHeight() {
	return this->Height_Max;
}
float Elevator::Get_MinHeight() {
	return this->Height_Min;
}
int Elevator::Get_FloorNum() {
	return this->Floor_Num;
}
string Elevator::Transform_Enum(State curr) {
	string state = "";
	switch (curr)
	{
	case Up:
		state = "上升";
		break;
	case Down:
		state = "下降";
		break;
	case Wait:
		state = "等待";
		break;
	}
	return state;
}
int Elevator::Get_StopFloor() {
	return this->Stop_Floor;
}
void Elevator::Set_StopFloor(int floor) {
	//限制停止楼层越界
	if (floor > this->Get_MaxFloor()) {
		this->Stop_Floor = this->Get_MaxFloor();
	}
	if (floor < this->Get_MinFloor()) {
		this->Stop_Floor = this->Get_MinFloor();
	}
	this->Stop_Floor = floor;
}
void Elevator::Show_ElevatorInfo() {
	int start = this->Minimun_Floor;
	string state = this->Transform_Enum(this->Current_State);
	cout << this->Elevator_Name << "信息:" << endl;
	cout << "电梯可到达最高楼层: " << this->Higest_Floor << " 最低楼层: " << this->Minimun_Floor << endl;
	cout << "电梯最大载重量: " << this->Weight_Max << endl;
	cout << "当前可选楼层: ";
	if (start > 0) {
		for (int i = start; i <= this->Floor_Num; i++) {
			cout << i << " ";
		}
	}
	if (start < 0) {
		for (int j = start; j < this->Floor_Num; j++) {
			if (j >= 0) {
				cout << j + 1 << " ";
			}
			else
			{
				cout << j << " ";
			}
		}
	}
	cout << endl;
	cout << "电梯初始化完毕------>状态: " << state << endl;
	cout << "电梯梯门准备-------->状态: " << this->Door_State << endl;
	cout << "当前所在楼层-------->" << this->Stop_Floor <<"楼"<< endl;
}
void Elevator::Run_Elevator(string dir) {
	int start = this->Stop_Floor;
	int end = 0;
	if (dir == "up") {
		end = this->Floor_Btn[this->Floor_Num - 1];  //向上取最大
		for (int i = 0; i <= this->Floor_Num - 1; i++) {
			if (this->Floor_Btn[i] == 0 || this->Floor_Btn[i] == start) { continue; }
			Sleep(UP_TIME);
			this->Current_State = Up;
			cout << this->Elevator_Name << " 正在上升-------->到达" << this->Floor_Btn[i] << "楼" << endl;
			//开启电梯门后的操作
			this->Open_Door();
			//到达最后的楼层停止
			if (this->Floor_Btn[i] == end) {
				Up_Button = false;  //释放上行按钮
				this->Stop_Floor = i;  //电梯最后停止楼层位置
				this->Current_State = Wait;
				cout << Up_Button << endl;
				this->Show_ElevatorInfo();
				break;
			}
		}
	}
	if (dir == "down") {
		end = this->Floor_Btn[0];  //向下取最小
		for (int j = start; j >= this->Minimun_Floor; j--) {
			if (this->Floor_Btn[j] == 0 || this->Floor_Btn[j] == start) { continue; }
			Sleep(UP_TIME);
			this->Current_State = Down;
			cout << this->Elevator_Name << " 正在下降-------->到达" << this->Floor_Btn[j] << "楼" << endl;
			//开启电梯门后的操作[待定]
			this->Open_Door();
			//到达最后的楼层停止
			if (this->Floor_Btn[j] == end) {
				Down_Button = false;  //释放下行按钮
				this->Stop_Floor = j;  //电梯最后停止楼层位置
				this->Current_State = Wait;
				break;
			}
		}
	}
}
void Elevator::Print_Line(int leng) {
	int index = leng;
	while (index >= 0)
	{
		cout << "-";
		index -= 1;
	}
	cout << endl;
}
void Elevator::Open_Door() {
	this->Door_State = "开启";
	cout << this->Elevator_Name << " 梯门准备-------->状态: " << this->Door_State << endl;
	Sleep(OPEN_TIME);
	this->Door_State = "关闭";
	cout << this->Elevator_Name << " 梯门准备-------->状态: " << this->Door_State << endl;
}

//楼层输入归纳
int* Input_FloorInduce(Elevator *ele) {
	int end = 0;
	int count = 0;  //计数[用以剔除多输入的楼层数]
	char num = '0';
	string numstr = "";
	stringstream strnum;
	int leng = ele->Get_FloorNum();
	char *floors = new char[leng * 3];
	int *floors_num = new int[leng];
	end = leng * 3;
	cout << "请输入要到达的楼层[使用空格间隔]: " << endl;
	cin.getline(floors, leng * 3, '\n');  //输入到达楼层
	//此处可以添加输入楼层字符的修正方法[可选]
	//切割输入楼层字符串,并转换为数字
	for (int i = 0; i < end; i++) {
		num = *(floors + i);
		if (num != ' ' && num != '\0') {
			numstr += num;
		}
		if (num == ' ' || num == '\0') {
			strnum << numstr;
			strnum >> *(floors_num + count);  // 将转换的数字赋值入数组
			//cout << *(floors_num + count) << endl;
			numstr = "";
			count += 1;
			strnum.clear();  //多次调用需要清空缓冲区
			if (num == '\0' || count == leng) {
				break;
			}
		}
	}
	//delete []floors;
	return floors_num;
}

void Elevator::Input_FloorBtn(Elevator *ele) {
	int leng = this->Floor_Num;
	int *induce = NULL;
	int *temp = NULL;
	induce = Input_FloorInduce(ele);
	temp = ele->Floor_Btn;
	//冒泡排序[从小到大排列]
	for (int i = 0; i < leng; i++) {
		for (int j = 0; j < leng - 1; j++) {
			if (*(induce + j) < ele->Minimun_Floor) {
				*(induce + j) = 0;
			}
			if (*(induce + j) > *(induce + j + 1)) {
				int temp = *(induce + j);
				*(induce + j) = *(induce + j + 1);
				*(induce + j + 1) = temp;
			}
		}
	}
	//将排序好的楼层序列赋值入电梯对象中的按下楼层数组
	for (int k = 0; k < leng; k++) {
		*(temp + k) = *(induce + k);
		cout << *(temp + k) << " ";
	}
	cout << endl;
	//释放动态数组空间
	induce = NULL;  //重置为NULL释放指向的数组
	temp = NULL;
	//delete induce;
	//delete temp;
}
//上行下行总输入方法
void  Input_TotalDirction() {
	string btn = "";
	while (true)
	{
		cout << "请输入需要的方向[up/down/up_down]:";
		cin >> btn;
		cin.clear();
		cin.ignore();
		if (btn._Equal("up")) {
			Up_Button = true;
			return;
		}
		if (btn._Equal("down")) {
			Down_Button = true;
			return;
		}
		if (btn._Equal("up_down")) {
			Down_Button = true;
			Up_Button = true;
			return;
		}
		cout << "输入不正确请重新输入!" << endl;
	}
}
void Show_Run(Elevator *ele,string dir) {
	ele->Run_Elevator(dir);
}
template <typename T>
//获取数组长度
int Get_ArrayLength(T& arr) {
	int a = sizeof(arr);
	int b = sizeof(arr[0]);
	int index = sizeof(arr) / sizeof(arr[0]);
	return index;
}
//筛选当前可执行的电梯
void Choice_Elevator(Elevator *ele[]) {
	int end = 0;
	Elevator *Temp = NULL;
	bool is_up = Up_Button;
	bool is_down = Down_Button;
	for (int i = 0; i < ElevatorSum; i++) {
		Temp = ele[i];
		if (Temp->Current_State == Wait) {
			if (is_up == true) {
				//上行，电梯当前位置不得大于等于最大楼层
				if (Temp->Get_StopFloor() < Temp->Get_MaxFloor()) {
					Temp->Input_FloorBtn(Temp);
					thread Ele_1(Show_Run, Temp, "up");
					Ele_1.join();
					continue;
				}
			}
			if (is_down == true) {
				//下行，电梯当前位置不得小于等于最小楼层
				if (Temp->Get_StopFloor() > Temp->Get_MinFloor()) {
					Temp->Input_FloorBtn(Temp);
					thread Ele_2(Show_Run, Temp, "down");
					Ele_2.join();
					continue;
				}
			}

		}
	}
}
//定时器[使用函数指针]
void  Timer(void(*call)(Elevator *arr[]),Elevator *ele[],int interval) {
	while (true)
	{
		Input_TotalDirction();
		Sleep(interval);
		call(ele);
	}
}

int main()
{
	Elevator *EleOne = new Elevator();
	Elevator *EleTwo = new Elevator();
	EleOne->Elevator_Name = "电梯A";
	EleOne->Show_ElevatorInfo();
	EleOne->Print_Line(50);
	EleTwo->Elevator_Name = "电梯B";
	EleTwo->Set_StopFloor(5);
	EleTwo->Show_ElevatorInfo();
	EleTwo->Print_Line(50);
	Elevator *Ele[2] = { EleOne,EleTwo };
	ElevatorSum = Get_ArrayLength(Ele);
	//EleOne->Input_FloorBtn(EleOne);
	Timer(Choice_Elevator,Ele,1000);
	delete EleOne;
	delete EleTwo;
	return 0;
}


